package com.jintian.smart.kernel.orm.entity.annotation;

import com.jintian.smart.kernel.common.util.StringUtil;
import org.beetl.sql.annotation.builder.AttributeConvert;
import org.beetl.sql.annotation.builder.UpdateTime;
import org.beetl.sql.clazz.kit.BeanKit;
import org.beetl.sql.clazz.kit.BeetlSQLException;
import org.beetl.sql.core.ExecuteContext;
import org.springframework.util.ReflectionUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ListMapperConvert implements AttributeConvert {

    @SuppressWarnings("rawtypes")
    @Override
    public Object toAttr(ExecuteContext ctx, Class cls, String name, ResultSet rs, int index) throws SQLException {
        Object value = rs.getObject(index);
        if (value == null) {
            return new ArrayList<>();
        }
        String content = null;
        try {
            if (value instanceof String)
                content = ((String) value);
            else if (value instanceof byte[]) {
                content = new String((byte[]) value, "utf-8");
            } else if (value instanceof Clob) {
                content = this.clob2String((Clob) value);
            } else if (value instanceof Blob) {
                content = this.blob2String((Blob) value);
            } else {
                throw new BeetlSQLException(BeetlSQLException.ANNOTATION_DEFINE_ERROR,
                        "不支持 " + value.getClass() + "转换为String类型");
            }
        } catch (Exception e) {
            throw new BeetlSQLException(BeetlSQLException.ANNOTATION_DEFINE_ERROR, value + "转换为String异常", e);
        }
        Field filed = ReflectionUtils.findField(cls, name);
        ListMapper mapper = filed.getAnnotation(ListMapper.class);
        return new ArrayList<>(Arrays.asList(content.split(mapper.value())));
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    @UpdateTime
    public Object toDb(ExecuteContext ctx, Class cls, String name, Object pojo) {
        if (pojo == null)
            return null;
        if (!cls.isAssignableFrom(pojo.getClass())) {
            return null;
        }
        Field filed = ReflectionUtils.findField(cls, name);
        ListMapper mapper = filed.getAnnotation(ListMapper.class);
        List value = (List) BeanKit.getBeanProperty(pojo, name);
        return StringUtil.join(value, mapper.value());

    }

    /**
     * @return
     * @throws SQLException
     * @see com.alibaba.druid.support.spring.DruidLobHandler
     */
    private String clob2String(Clob clob) throws SQLException {
        if (clob == null) {
            return null;
        }

        return clob.getSubString(1, (int) clob.length());
    }

    private String blob2String(Blob blob) throws SQLException, IOException {
        if (blob == null) {
            return null;
        }
        InputStream in = blob.getBinaryStream();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buff = new byte[8192];
        int len = -1;
        while ((len = in.read(buff, 0, buff.length)) != -1) {
            out.write(buff, 0, len);
        }
        in.close();
        return out.toString("utf-8");
    }
}
